import { type Options } from "./type";
import Edit from "./edit";
import { v4 } from "uuid";
import { onBeforeUnmount, watch, onMounted } from "vue";
import NP from "number-precision";
import { getCopyPasteTextarea, readTextToClipboard, writeTextToClipboard } from "./util";

export default class extends Edit {
  constructor(options: Options) {
    super(options);

    getCopyPasteTextarea();
    const keypressCtrlC = () => this.keypressCtrlC();
    const keypressCtrlV = () => this.keypressCtrlV();

    onMounted(() => {
      document.addEventListener("keydown", keypressCtrlC);
      document.addEventListener("keydown", keypressCtrlV);
    });

    onBeforeUnmount(() => {
      document.removeEventListener("keydown", keypressCtrlC);
      document.removeEventListener("keydown", keypressCtrlV);
    });
  }

  private copyData: any[][] = [];

  private cellSplit = "\t";

  private warpSplit = "\r";

  private enterSplit = "\n";

  // 向下复制
  copydownHandel() {
    if (this.getMinStartY() !== this.getMaxEndY()) {
      this.warningMsg(/*"不能对多重选择区域执行此操作"*/ this.getMessage('disabledMoreArea').value);
      return;
    }

    if (this.selectedState.rows && this.selectedState.cells) {
      this.warningMsg(/*"不能对多重选择区域执行此操作"*/ this.getMessage('disabledMoreArea').value);
      return;
    }

    let copyIndexRow = this.getMaxEndY();
    let copyIndexCol = this._getMinStartX();

    const lastRowIndex = this.props?.keepLastRowEmpty
      ? this.dataSource.value?.length - 2
      : this.dataSource.value?.length - 1;
    while (copyIndexRow < lastRowIndex) {
      copyIndexRow++;
      while (copyIndexCol <= this._getMaxEndX()) {
        const dataIndex = this.columns?.value[copyIndexCol].dataIndex;
        const value = this.getValueByModel(
          dataIndex,
          this.dataSource?.value[this.getMinStartY()]
        );

        this.setValueByModel(
          dataIndex,
          this.dataSource.value[copyIndexRow],
          value
        );
        copyIndexCol++;
      }
      copyIndexCol = this._getMinStartX();
    }
  }

  // 向下递增
  async addStepdownHandel(step: number = 1) {
    if (this.getMinStartY() !== this.getMaxEndY()) {
      this.warningMsg("不能对多行选择区域执行此操作");
      return;
    }

    if (this.selectedState.rows && this.selectedState.cells) {
      this.warningMsg("不能对多重选择区域执行此操作");
      return;
    }

    let copyIndexRow = this.getMaxEndY();
    let copyIndexCol = this._getMinStartX();

    let count: any = {};

    const lastRowIndex = this.props.keepLastRowEmpty
      ? this.dataSource?.value.length - 2
      : this.dataSource?.value.length - 1;

    while (copyIndexRow < lastRowIndex) {
      copyIndexRow++;
      while (copyIndexCol <= this._getMaxEndX()) {
        const dataIndex = this.columns?.value[copyIndexCol].dataIndex; // 列key

        let value = this.getValueByModel(
          dataIndex,
          this.dataSource?.value[this.getMinStartY()]
        ); // 起始值

        count[copyIndexCol] = NP.plus(count[copyIndexCol] || 0, step);
        if (Number(value) == value) {
          value = NP.plus(value, count[copyIndexCol]);
        } else if (/(\d+)$/g.exec(value)) {
          const exResult: any = /(\d+)$/g.exec(value);
          const num = NP.plus(exResult[0], count[copyIndexCol]);
          value = `${value.substring(0, exResult.index)}${num}`;
        } else {
          value = value + count[copyIndexCol];
        }

        this.setValueByModel(
          dataIndex,
          this.dataSource.value[copyIndexRow],
          value
        );
        copyIndexCol++;
      }
      copyIndexCol = this._getMinStartX();
    }
  }

  // 复制
  copyHandel() {
    if (this.selectedState.rows && this.selectedState.cells) {
      this.warningMsg(/*"不能对多重选择区域执行此操作"*/ this.getMessage('disabledMoreArea').value);
      return;
    }

    this.copyData = [];
    let copytext: string = "";

    if (this.selectedState.cells || this.selectedState.rows) {
      copytext = this.getCopyDataAnyWhereSelected() as string;
    } else {
      copytext = this.getCopyData() as string;
    }

    writeTextToClipboard(copytext)
  }

  // 从剪辑版获取数据
  async getClipboardData(): Promise<any[][]> {
    const clipboardData = await readTextToClipboard();
    return (clipboardData && this.pasteToJson(clipboardData)) || [];
  }
  pasteToJson(text: string) {
    try {
      if (text.startsWith("[") && text.endsWith("]")) {
        const data = JSON.parse(text) ?? undefined;
        if (typeof data === "object") return data;
        throw "";
      } else {
        throw "";
      }
    } catch (e) {
      return text
        .replace(RegExp(`${this.enterSplit}`, "g"), "")
        .split(this.warpSplit)
        .map((row) => row.split(this.cellSplit));
    }
  }
  // 粘贴
  async pasteHandel() {
    if (this.checkHasReadonly(this.selectAreasData.value.records)) return;
    if (this.checkHasDisable(this.selectAreasData.value.records)) return;

    if (this.props.customEditer?.onEditBefore){
      await this.props.customEditer?.onEditBefore?.(this.selectAreasData.value, this);
    }
    
    // 存在自由点选时， 不允许进行粘贴
    if (this.selectedState.cells || this.selectedState.rows) {
      this.warningMsg(/*"不能对多重选择区域执行此操作"*/ this.getMessage('disabledMoreArea').value);
      return;
    }

    if(this.props.openUndo && this.emptyHistoryRecord()) this.addHistoryRecord();

    this.copyData = await this.getClipboardData();

    if (this.copyData.length === 0) return;

    let minRowindex = this.getMinStartY();
    let maxRowindex = Math.max(
      this.getMaxEndY(),
      minRowindex + this.copyData.length - 1
    );
    let minColindex = this._getMinStartX();
    let maxColindex = Math.max(
      this._getMaxEndX(),
      minColindex + this.copyData[0].length - 1
    );

    let copyDataRowIndex = 0;
    let copyDataColIndex = 0;
    do {
      // 行复制
      if (this.selectedState.startX === -1) {
        if (!this.copyData[copyDataRowIndex]) copyDataRowIndex = 0;

        this.dataSource.value[minRowindex] = {
          ...JSON.parse(JSON.stringify(this.copyData[copyDataRowIndex])),
          [this.props.rowKey]: v4(),
        };
      } else {

        // 行不够，自动添加行
        if (this.dataSource.value[minRowindex] === undefined) {
          this.insertRows?.(minRowindex, 'after', 1, false);
        }

        if (!this.copyData[copyDataRowIndex]) copyDataRowIndex = 0;

        copyDataColIndex = 0;
        const copyDataRow = this.copyData[copyDataRowIndex];
        if (!copyDataRow) break;

        do {
          if (copyDataColIndex >= copyDataRow.length) copyDataColIndex = 0;

          const copyDataCol = copyDataRow[copyDataColIndex];
          const customPaste = this.columns?.value[minColindex].customPaste;
          const dataIndex = this.columns?.value[minColindex]?.dataIndex;
          const valueType = this.columns?.value[minColindex]?.valueType;

          if (typeof customPaste === 'function'){
            customPaste({
              value: window.decodeURIComponent(copyDataCol), // 解码
              rowindex: minRowindex,
              record: this.dataSource.value[minRowindex],
              source: this.dataSource,
            }, this.selectAreasData.value);

          } else if (dataIndex) {
            let value = [undefined, null, ""].includes(copyDataCol)
              ? undefined
              : copyDataCol;
            if (value !== undefined && valueType === "number"){
              value = isNaN(value) ? undefined : Number(value);
            } else if (value !== undefined && valueType === "boolean"){
              const EUMNS: any = {
                true: true,
                false: false,
                "1": true,
                "0": false,
              }
              value = EUMNS[value];
            }

            this.setValueByModel(
              dataIndex,
              this.dataSource.value[minRowindex],
              value
            );
          }

          minColindex++;
          copyDataColIndex++;
        } while (minColindex <= maxColindex);
        minColindex = this._getMinStartX();
      }

      minRowindex++;
      copyDataRowIndex++;
    } while (minRowindex <= maxRowindex);

    if(this.props.openUndo) this.addHistoryRecord();
  }

  private _getMinStartX() {
    if (this.selectedState.startX === -1) return 0;
    return Math.min(
      this.selectedState.startX ?? 0,
      this.selectedState.endX ?? 0
    );
  }
  private _getMaxEndX() {
    if (this.selectedState.startX === -1)
      return this.columns?.value?.length - 1;
    return Math.max(
      this.selectedState.startX ?? 0,
      this.selectedState.endX ?? 0
    );
  }

  // 获取复制数据
  private getCopyData() {
    // 行复制
    if (this.selectedState.startX === -1) {
      const copyData = this.dataSource?.value.slice(this.getMinStartY(), this.getMaxEndY() + 1)?? [];
      return JSON.stringify(copyData);
    }
    let copyIndexRow = this.getMinStartY();
    let copyIndexCol = this._getMinStartX();
    let copytext = "";
    const copyThTitle = [];
    do {
      // 添加换行符
      if (copytext !== "") {
        copytext += this.warpSplit;
      }
      const cpdata: any = [];
      do {
        // 首行添加表头
        if (
          this.selectedState.selectedTh &&
          copyIndexRow === this.getMinStartY()
        ) {
          const th = this.getCellElement({colindex: copyIndexCol});
          copyThTitle.push(th?.innerText ?? '');
        }
        // 添加制表符
        if (copyIndexCol > this._getMinStartX()) {
          copytext += this.cellSplit;
        }

        const customCopy = this.columns?.value[copyIndexCol].customCopy;
        const dataIndex = this.columns?.value[copyIndexCol].dataIndex;
        let value = "";
        try{
          if (typeof customCopy === 'function') {
            value = customCopy({
              value, 
              rowindex: copyIndexRow, 
              record: this.dataSource?.value[copyIndexRow], 
              source: this.dataSource
            }, this.selectAreasData.value) || '';
  
            if(typeof value !== 'string') {
              console.error('customCopy 返回值不是一个字符串. 请检查返回值.');
            }
            // 编码
            value = window.encodeURIComponent(value);
          } else {
            value = this.getValueByModel(
              dataIndex,
              this.dataSource?.value[copyIndexRow]
            ) ?? "";
          }
  
          cpdata.push(value);
  
          // if (false && this.columns?.value[copyIndexCol].type === "select") {
          //   const td = this.getCellElement({rowindex: copyIndexRow, colindex: copyIndexCol});
          //   copytext += td?.innerText || value;
          // } else {
          //   copytext += value;
          // }
        } catch(e){ }finally{
          copytext += value;
          copyIndexCol++;
        }
      } while (copyIndexCol <= this._getMaxEndX());
      copyIndexCol = this._getMinStartX();
      copyIndexRow++;
      this.copyData.push(cpdata);
    } while (copyIndexRow <= this.getMaxEndY());

    if (this.selectedState.selectedTh) {
      return copyThTitle.join(this.cellSplit) + this.warpSplit + copytext;
    }
    return copytext;
  }
  // 获取自由点选复制数据
  private getCopyDataAnyWhereSelected() {
    if (this.selectedState.rows) {
      return JSON.stringify(
        this.selectedState.rows.map((rowindex) => {
          return this.dataSource.value[rowindex];
        })
      );
    }

    if (this.selectedState.cells) {
      // 自由点选单元格时，存在不同行、不同列时， 不允许复制
      // 是否都在一行 或者 是否都在一列
      const sameRow =
        new Set(this.selectedState.cells.map((v) => v[0])).size === 1;
      const sameCol =
        new Set(this.selectedState.cells.map((v) => v[1])).size === 1;
      if (!(sameRow || sameCol)) {
        this.warningMsg(/*"不能对多重选择区域执行此操作"*/ this.getMessage('disabledMoreArea').value);
        throw this.getMessage('disabledMoreArea').value;
      }

      // 同一行中
      if (sameRow) {
        const colindexs = this.selectedState.cells.map((v) => v[1]);
        const rowindex = this.selectedState.cells[0][0];
        let text: string = "";
        let startX = Math.min(...colindexs);
        const endX = Math.max(...colindexs);

        while (startX <= endX) {
          if (colindexs.includes(startX)) {
            // TODO 含表头的复制
            if (rowindex === -1) {
              if (text !== "") text += this.cellSplit;
              const th = this.getCellElement({colindex: startX});
              text += th?.innerText;
            } else {
              if (text !== "") text += this.cellSplit;
              const dataIndex = this.columns?.value[startX].dataIndex;
              const value =
                this.getValueByModel(
                  dataIndex,
                  this.dataSource?.value[rowindex]
                ) ?? "";
              text += value;
            }
          }
          startX++;
        }

        return text;
      }

      // 同一列中
      if (sameCol) {
        const rowindexs = this.selectedState.cells.map((v) => v[0]);
        const colindex = this.selectedState.cells[0][1];
        const dataIndex = this.columns?.value[colindex].dataIndex;
        let text: string = "";
        let startY = Math.min(...rowindexs);
        const endY = Math.max(...rowindexs);

        while (startY <= endY) {
          if (rowindexs.includes(startY)) {
            // TODO 含表头的复制
            if (startY === -1) {
              text += this.getCellElement({colindex: colindex})?.innerText ?? '';
            } else {
              if (text !== "") text += this.warpSplit;
              const value =
                this.getValueByModel(
                  dataIndex,
                  this.dataSource?.value[startY]
                ) ?? "";
              text += value;
            }
          }
          startY++;
        }

        return text;
      }
    }
  }

  // Ctrl+C
  private keypressCtrlC = () => {
    if (!this.currentView) return;

    if ((event?.ctrlKey || event?.metaKey) && event?.keyCode == 67) {
      this.copyHandel();
      return false;
    }
  };

  // Ctrl+V
  private keypressCtrlV = () => {
    if (!this.currentView) return;
    if ((event?.ctrlKey || event?.metaKey) && event?.keyCode == 86) {
      this.pasteHandel();
      return false;
    }
  };
}
